package com.bifrost.service.impl;

import com.bifrost.constant.CommentStatus;
import com.bifrost.constant.OrderStatus;
import com.bifrost.constant.OrderType;
import com.bifrost.entity.*;
import com.bifrost.model.CustomerModel;
import com.bifrost.common.model.ResultModel;
import com.bifrost.model.review.ReviewRequest;
import com.bifrost.model.review.ReviewResult;
import com.bifrost.repository.*;
import com.bifrost.service.*;
import com.bifrost.util.DateUtils;
import com.bifrost.util.LocalDateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.util.*;

/**
 * @author rangf
 * @date 2017/11/13
 */
@Service
public class ProductReviewServiceImpl implements ProductReviewService {

    @Autowired
    CustomerRepository customerRepository;
    @Autowired
    ProductRepository productRepository;
    @Autowired
    ProductReviewRepository reviewRepository;
    @Autowired
    MediaRepository mediaRepository;
    @Autowired
    CustomerService customerService;
    @Autowired
    OrderService orderService;
    @Autowired
    ProductSkuService skuService;
    @Autowired
    OrderItemRepository orderItemRepository;
    @Autowired
    OrderStatusHistoryService orderStatusHistoryService;

    /**
     * 发布商品评论
     *
     * @param customer
     * @param orderId
     * @param models
     * @param needConfirm 是否需要审核 true为需要审核false为不需要审核
     * @return
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public ResultModel addReview(Customer customer, Long orderId, List<ReviewRequest> models, boolean needConfirm) {
        Order order = orderService.findOrderById(orderId);
        //优惠券订单直接修改订单评论状态
        if (OrderType.CASH_BY_COUPON.equalsIgnoreCase(order.getOrderType())) {
            order.setCommentStatus(CommentStatus.COMMENTED);
            return ResultModel.ok("成功");
        }
        if(order != null && OrderStatus.FINISHED.equals(order.getOrderStatus()) ){
            for(ReviewRequest model : models) {
                ProductReview review = new ProductReview();
                review.setCustomersId(customer.getCustomerId());
                ProductSku sku = skuService.getSkuById(model.getSkuId());
                review.setProduct(sku.getProduct());
                review.setProductSku(sku);
                review.setReviewDate(new Date());
                review.setReviewDescription(model.getDesc());
                review.setReviewRating(model.getRank());
                review.setReviewMediaMaps(new ArrayList<>());
                review.setUpdatedTimestamp(new Date());
                if(!needConfirm){
                    review.setReviewStatus(1);
                }
                /*String mediaIds = model.getMediaIds();
                if (StringUtils.isNotBlank(mediaIds)) {
                    review.setHasMedia(Boolean.TRUE);
                    String[] arrays = mediaIds.split(",");
                    for (String mediaId : arrays) {
                        Media media = mediaRepository.getOne(Long.parseLong(mediaId));
                        ReviewMediaMap reviewMediaMap = new ReviewMediaMap();
                        reviewMediaMap.setMapKey("PRIMARY");
                        reviewMediaMap.setMedia(media);
                        reviewMediaMap.setProductReview(review);
                        review.getReviewMediaMaps().add(reviewMediaMap);
                    }
                } else {
                    review.setHasMedia(Boolean.FALSE);
                }
                */
                ProductSku defaultSku = skuService.getDefaultSku(sku);
                if(defaultSku != null){
                    if (sku.getReviewAVG() == null) {
                        defaultSku.setReviewAVG(1L);
                    } else {
                        defaultSku.setReviewAVG(sku.getReviewAVG() + 1L);
                    }
                    skuService.saveSku(defaultSku);
                }
                reviewRepository.save(review);
            }
            order.setCommentStatus(CommentStatus.COMMENTED);
            return ResultModel.ok("成功");
        }
        return ResultModel.error("失败");
    }

    /**
     * 获取商品所有评论信息
     *
     * @param skuId    skuId
     * @param page     页数
     * @param pageSize 每页大小
     * @param flag     评论有图：有1，否0
     * @return Map
     */
    @Override
    public Map getReviews(Long skuId, Integer page, Integer pageSize, String flag) {
        ProductSku sku = skuService.getSkuById(skuId);
        Product product = sku.getProduct();
        Map reviewsMap = new HashMap(3);
        reviewsMap.put("reviews", null);
        reviewsMap.put("reviewCountWithMedia", 0);
        reviewsMap.put("reviewCount", 0);
        Pageable pageable = new PageRequest(page - 1, pageSize, new Sort(Sort.Direction.DESC, "reviewDate"));
        Specification<ProductReview> query = new Specification<ProductReview>() {
            @Override
            public Predicate toPredicate(Root<ProductReview> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.isNull(root.get("parentReview")));
                predicates.add(cb.equal(root.get("product"), product));
                predicates.add(cb.equal(root.get("reviewStatus"), 1));
                if ("1".equals(flag)) {
                    predicates.add(cb.equal(root.get("hasMedia"), Boolean.TRUE));
                }
                Predicate[] p = new Predicate[predicates.size()];
                return cb.and(predicates.toArray(p));
            }
        };
        Page<ProductReview> data = reviewRepository.findAll(query, pageable);
        if (data != null && data.hasContent()) {
            List<ReviewResult> reviews = new ArrayList<>();
            data.getContent().forEach(productReview -> {
                //注释为评论回复
            /*ReviewResult result = convertToReviewResult(productReview);
            result.setChildrens(new ArrayList<>());
            List<ProductReview> childrens = reviewRepository.findAllByParentReview(productReview.getProductReviewId());
            if (childrens != null && !childrens.isEmpty()) {
                childrens.forEach(review -> {
                    result.getChildrens().add(convertToReviewResult(review));
                });
            }*/
                reviews.add(convertToReviewResult(productReview));
            });
            reviewsMap.put("reviews", reviews);
            reviewsMap.put("reviewCountWithMedia", null);
            Integer reviewCount = reviewRepository.countFinalSkuReview(product.getDefaultSku());
            reviewsMap.put("reviewCount", reviewCount==null?0:reviewCount);
            //Long reviewCountWithMedia = reviewRepository.countByProductAndHasMedia(product, Boolean.TRUE);
            //reviewsMap.put("reviewCountWithMedia", reviewCountWithMedia.toString());
            //reviewsMap.put("review", product.getDefaultSku().getReviewCount());
            return reviewsMap;
        }
        return reviewsMap;
    }

    public ReviewResult convertToReviewResult(ProductReview productReview) {
        ReviewResult model = new ReviewResult();
        CustomerModel customerModel = customerService.getCustomerModel(productReview.getCustomersId());
        model.setId(productReview.getProductReviewId());
        model.setAvatar(customerModel.getAvatar());
        model.setDate(DateUtils.format(productReview.getReviewDate(), "yyyy.MM.dd"));
        model.setDesc(productReview.getReviewDescription());
        model.setLevel(productReview.getReviewRating());
        if (productReview.getParentReview() != null) {
            model.setParentId(productReview.getProductReviewId());
        }
        model.setName(customerModel.getName());
        /*List<ReviewMediaMap> mediaMaps = productReview.getReviewMediaMaps();
        List<Media> medias = new ArrayList<>();
        if (mediaMaps != null && !mediaMaps.isEmpty()) {
            mediaMaps.forEach(reviewMediaMap -> {
                medias.add(reviewMediaMap.getMedia());
            });
        }
        List<String> urls = new ArrayList<>();
        if (!medias.isEmpty()) {
            urls = medias.stream().map(Media::getUrl).collect(Collectors.toList());
        }
        model.setReviewImgs(urls);*/
        return model;
    }

    /**
     * 构建评论request:用于自动好评
     *
     * @param order
     * @return
     */
    @Override
    public List<ReviewRequest> BuildReviewRequest(Order order) {
        List<OrderItem> orderItems = order.getOrderItems();
        List<ReviewRequest> reviewRequests = null;
        if(orderItems != null && !orderItems.isEmpty()){
            reviewRequests = new ArrayList<>();
            for (OrderItem item : orderItems) {
                ReviewRequest request = new ReviewRequest();
                request.setSkuId(item.getSkuId());
                request.setRank(5);
                request.setDesc("系统自动评价");
                reviewRequests.add(request);
            }
            return reviewRequests;
        }
        return null;
    }

    /**
     * 自动评论<br>
     * 注：不需要审核，立即生效
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public void autoReview() {
        List<Order> orderList = orderService.findAllNotCommentOrder();
        if(CollectionUtils.isNotEmpty(orderList)){
            for (Order order : orderList) {
                Date receiveDate = orderStatusHistoryService.getTime(order.getOrderId(), OrderStatus.FINISHED);
                LocalDate autoReviewDate = LocalDateUtils.fromDate(receiveDate).plusDays(30);
                if(autoReviewDate.isBefore(LocalDate.now())){
                    addReview(order.getCustomer(), order.getOrderId(), BuildReviewRequest(order),false);
                }
            }
        }
    }

}
